-
Notifications
You must be signed in to change notification settings - Fork 9
add FieldName API #79
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you checked through other rules to see if there are other places that could use this util?
pkg/analysis/jsontags/analyzer.go
Outdated
prefix := "embedded field %s" | ||
if len(field.Names) > 0 && field.Names[0] != nil { | ||
prefix = fmt.Sprintf("field %s", field.Names[0].Name) | ||
} else if ident, ok := field.Type.(*ast.Ident); ok { | ||
prefix = fmt.Sprintf("embedded field %s", ident.Name) | ||
prefix = "field %s" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit, embedded fields are the exception, not the rule, so I would invert this
prefix := "field %s"
if len(field.Names) == 0 || field.Names[0] == nil {
prefix = "embedded field %s"
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, fixed.
pkg/analysis/jsontags/analyzer.go
Outdated
} | ||
|
||
if tagInfo.Missing { | ||
pass.Reportf(field.Pos(), "%s is missing json tag", prefix) | ||
pass.Reportf(field.Pos(), "%s is missing json tag", fmt.Sprintf(prefix, utils.FieldName(field))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably better to call the FieldName
once/twice when we are setting up the prefix, than three times down here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
pkg/analysis/utils/utils.go
Outdated
// FieldName returns the name of the field. If the field has a name, it returns that name. | ||
// If the field is embedded and it can be converted to an identifier, it returns the name of the identifier. | ||
func FieldName(field *ast.Field) string { | ||
if len(field.Names) > 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check as well that Names[0]
isn't nil
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
5b9b769
to
97ea957
Compare
@@ -77,6 +77,21 @@ func LookupTypeSpec(pass *analysis.Pass, ident *ast.Ident) (*ast.TypeSpec, bool) | |||
return nil, false | |||
} | |||
|
|||
// FieldName returns the name of the field. If the field has a name, it returns that name. | |||
// If the field is embedded and it can be converted to an identifier, it returns the name of the identifier. | |||
func FieldName(field *ast.Field) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the expected fieldName for pointer embedded fields? e.g.
*StringPtrField `json:"stringPtrField"`
Under current implementation, it would be ""
. Should the output be *StringPtrField
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Thanks, fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we create some test cases for this function that demonstrate it's functionality? Make sure if we make updates here in the future we don't forget why we are handling StarExpr?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added test cases
Signed-off-by: sivchari <shibuuuu5@gmail.com>
Signed-off-by: sivchari <shibuuuu5@gmail.com>
Signed-off-by: sivchari <shibuuuu5@gmail.com>
Signed-off-by: sivchari <shibuuuu5@gmail.com>
Signed-off-by: sivchari <shibuuuu5@gmail.com>
0d2b0d5
to
90cf8be
Compare
pkg/analysis/utils/utils_test.go
Outdated
func TestFieldName(t *testing.T) { | ||
t.Parallel() | ||
|
||
cases := map[string]struct { | ||
field *ast.Field | ||
want string | ||
}{ | ||
"field has Names": { | ||
field: &ast.Field{ | ||
Names: []*ast.Ident{ | ||
{ | ||
Name: "foo", | ||
}, | ||
}, | ||
}, | ||
want: "foo", | ||
}, | ||
"filed has no Names, but is an Ident": { | ||
field: &ast.Field{ | ||
Type: &ast.Ident{ | ||
Name: "foo", | ||
}, | ||
}, | ||
want: "foo", | ||
}, | ||
"field has no Names, but is a StarExpr with an Ident": { | ||
field: &ast.Field{ | ||
Type: &ast.StarExpr{ | ||
X: &ast.Ident{ | ||
Name: "foo", | ||
}, | ||
}, | ||
}, | ||
want: "foo", | ||
}, | ||
"field has no Names, and is not an Ident or StarExpr": { | ||
field: &ast.Field{ | ||
Type: &ast.ArrayType{ | ||
Elt: &ast.Ident{ | ||
Name: "foo", | ||
}, | ||
}, | ||
}, | ||
want: "", | ||
}, | ||
} | ||
|
||
for name, tc := range cases { | ||
t.Run(name, func(t *testing.T) { | ||
t.Parallel() | ||
|
||
got := utils.FieldName(tc.field) | ||
if got != tc.want { | ||
t.Errorf("got %q, want %q", got, tc.want) | ||
} | ||
}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use ginkgo? Since other tests are using ginkgo already. The example below would show how this would look
func TestUtils(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Utils")
}
var _ = Describe("FieldName", func() {
type fieldNameTestCase struct {
field *ast.Field
want string
}
DescribeTable("Should extract the field name", func(tc fieldNameTestCase) {
Expect(utils.FieldName(tc.field)).To(Equal(tc.want), "expected the extracted field name to match)
},
Entry("field has Name", fieldNameTestCase{
field: &ast.Field{
Names: []*ast.Ident{
{
Name: "foo",
},
},
},
want: "foo",
}),
...
)
})
The actual TestUtils conventionally goes in a utils_suite_test.go
file on its own
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I rewrote the test case'
Signed-off-by: sivchari <shibuuuu5@gmail.com>
/approve |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: JoelSpeed, sivchari The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Add FieldName API to reduce the redundant code.
FieldName returns the name of filed, then if the field name is empty that means embedded field, return ident.Name instead.
/cleanup